#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "DirectedRelationship.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Classifier;
class GeneralizationSet;

/// <summary>
/// Generalization
/// A Generalization is a taxonomic relationship between a more general Classifier
/// and a more specific Classifier. Each instance of the specific Classifier is also
/// an instance of the general Classifier. The specific Classifier inherits the
/// features of the more general Classifier. A Generalization is owned by the
/// specific Classifier.
/// </summary>
class UMLMODEL_EXPORT Generalization : public DirectedRelationship {

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Properties
    /// <summary>
    /// general getter
    /// The general classifier in the Generalization relationship.
    /// </summary>
    shared_ptr<Classifier> general() const;

    /// <summary>
    /// general setter
    /// The general classifier in the Generalization relationship.
    /// </summary>
    void setGeneral(shared_ptr<Classifier> value);

    /// <summary>
    /// generalizationSets getter
    /// Represents a set of instances of Generalization.  A Generalization may appear in
    /// many GeneralizationSets.
    /// </summary>
    vector<shared_ptr<GeneralizationSet>>& generalizationSets();

    /// <summary>
    /// isSubstitutable getter
    /// Indicates whether the specific Classifier can be used wherever the general
    /// Classifier can be used. If true, the execution traces of the specific Classifier
    /// shall be a superset of the execution traces of the general Classifier. If false,
    /// there is no such constraint on execution traces. If unset, the modeler has not
    /// stated whether there is such a constraint or not.
    /// </summary>
    bool isSubstitutable() const;

    /// <summary>
    /// isSubstitutable setter
    /// Indicates whether the specific Classifier can be used wherever the general
    /// Classifier can be used. If true, the execution traces of the specific Classifier
    /// shall be a superset of the execution traces of the general Classifier. If false,
    /// there is no such constraint on execution traces. If unset, the modeler has not
    /// stated whether there is such a constraint or not.
    /// </summary>
    void setIsSubstitutable(bool value);

    /// <summary>
    /// specific getter
    /// The specializing Classifier in the Generalization relationship.
    /// </summary>
    shared_ptr<Classifier> specific() const;

    /// <summary>
    /// specific setter
    /// The specializing Classifier in the Generalization relationship.
    /// </summary>
    void setSpecific(shared_ptr<Classifier> value);

private: // Fields
    /// <summary>
    /// general
    /// The general classifier in the Generalization relationship.
    /// </summary>
    shared_ptr<Classifier> general_;

    /// <summary>
    /// generalizationSets
    /// Represents a set of instances of Generalization.  A Generalization may appear in
    /// many GeneralizationSets.
    /// </summary>
    vector<shared_ptr<GeneralizationSet>> generalizationSets_;

    /// <summary>
    /// isSubstitutable
    /// Indicates whether the specific Classifier can be used wherever the general
    /// Classifier can be used. If true, the execution traces of the specific Classifier
    /// shall be a superset of the execution traces of the general Classifier. If false,
    /// there is no such constraint on execution traces. If unset, the modeler has not
    /// stated whether there is such a constraint or not.
    /// </summary>
    const static bool isSubstitutable_default_;
    bool isSubstitutable_= isSubstitutable_default_;

    /// <summary>
    /// specific
    /// The specializing Classifier in the Generalization relationship.
    /// </summary>
    shared_ptr<Classifier> specific_;

};

} // namespace uml
